﻿/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 * Description: whiteboard 硬件加速sdk接口
 * Author: Huawei Technologies Co.
 * Create: 2022-1-14
 */

#ifndef PEN_SPEED_INTERFACE_H
#define PEN_SPEED_INTERFACE_H

namespace hwpenspeed {
using PointF = struct {
    float x;
    float y;
};

using FlushRect = struct {
    PointF pt;
    float width;
    float height;
};

using CanvasParam = struct {
    int posX;              // 起始位置，X轴 pixel 单位
    int posY;              // 起始位置，Y轴 pixel 单位
    int width;             // 画布大小 宽 pixel 单位
    int height;            // 画布大小 高 pixel 单位
    bool bDoubleBuffer;    // 是否双buffer缓存
};

using CanvasMap = struct {
    char* mapAddress;    // 映射的画布内存地址
    int rowStride;       // 映射画布内存每行字节数
    int bitsPerPixel;    // 每像素的bit位长
    int redOffset;       // 红色分量位偏移地址
    int redLength;       // 红色分量的位长
    int greenOffset;     // 绿色分量位偏移地址
    int greenLength;     // 绿色分量的位长
    int blueOffset;      // 蓝色分量位偏移地址
    int blueLength;      // 蓝色分量的位长
    int transpOffset;    // 透明分量位偏移地址
    int transpLength;    // 透明分量的位长
};

template<class T>
class point_vector {
enum {
    SPACE_CAPACITY = 4 // 初始容量
};
public:
    // 构造器与析构器
    // 用explicit避免隐式类型转换
    explicit point_vector(int size = 0)
        : m_size(size), m_capacity(size + SPACE_CAPACITY)
    {
        init();
    }
    // copy constructor
    point_vector(const point_vector& rhs) : _p(nullptr)
    {
        operator = (rhs);
    }
    ~point_vector()
    {
        delete[] _p;
    }

    // 运算符
    const point_vector& operator=(const point_vector& rhs)
    {
        if (this != &rhs) { // 如果是本身的话就不用再操作了
            delete [] _p;
            m_size = rhs.size();
            m_capacity = rhs.capacity();

            _p = new T[ capacity() ];
            for (int k = 0; k < m_size; k++) { // 拷贝元素
                _p[k] = rhs._p[k];
            }
        }
        return *this;
    }
    T& operator[](int index)
    {
        return _p[ index ];
    }
    const T& operator[](int index) const
    {
        return _p[ index ];
    }

    // 指针， iterator 操作

    using iterator = T*; // 用原生指针替代迭代器
    using const_iterator = const T*;
    iterator begin()
    {
        return &_p[0];
    }
    const_iterator begin() const
    {
        return &_p[0];
    }
    iterator end()
    {
        return &_p[m_size];
    }
    const_iterator end() const
    {
        return &_p[m_size];
    }
    void init()
    {
        _p = new T[m_capacity];
    }

    // 插入元素, 弹出元素

    void push_back(const T& x)
    {
        if (m_size == m_capacity) {
            ReAllocate(2 * m_capacity + 1);
        }
        _p[m_size++] = x;
    }
    void pop_back()
    {
        m_size--;
    }

    // 属性接口
    int size() const
    {
        return m_size;
    }
    int capacity() const
    {
        return m_capacity;
    }
    bool empty() const
    {
        return size() == 0;
    }
    const T& back() const
    {
        return _p[m_size - 1];
    }
private:
    int m_size; // 元素的个数
    int m_capacity; // 容量
    T *_p; // 指向new分配的资源

    // 内存分配（分配器简化处理）
    void resize(int newSize)
    {
        if (newSize > m_capacity) {
            ReAllocate(newSize * 2); // 每次空间不够的时候,就重新获得2倍于当前容量的空间
        }
        m_size = newSize;
    }
    // 获取新的空间,拷贝,释放旧的数据
    void ReAllocate(int newCapacity)
    {
        if (newCapacity < m_size) {
            return;
        }
        T *oldArray = _p;
        _p = new T[newCapacity];
        for (int k = 0; k < m_size; k++) {
            _p[k] = oldArray[k];
        }
        m_capacity = newCapacity;
        delete [] oldArray;
    }
};

class PenSpeedInterface {
public:
    PenSpeedInterface() {};
    virtual ~PenSpeedInterface() {};

    /*
     * @brief 创建PenSpeedInterface对象，返回指针
     * @param [in] serverBinder: android P传入nullptr， android Q以及后版本传入AIBinder*类型的指针
     * @return PenSpeedInterface指针 不为nullptr 成功; 否则 失败，
     *      指针指向对象所有权属于外部，外部需要管理，释放需要delete
     */
    static PenSpeedInterface* Create(void* serverBinder);

    /*
     * @brief 设置点处理的回调
     * @param [in] callback: 回调函数地址
     *      回调函数参数1： pointerId, 安卓OnTouch事件中的触点Id
     *      回调函数参数2： point, 类型为PointF的点坐标，参考系原点为CreateCanvas指定的Canvas左上角
     */
    void SetCallback(void (*callback)(int, PointF));

    /*
     * @brief 创建fb画布
     * @param [in] param: 指定显示画布的范围, 屏幕坐标
     * @return CanvasMap指针 不为nullptr 成功; 否则 失败， 指针指向对象所有权属于内部，外部不可delete
     */
    const CanvasMap* CreateCanvas(CanvasParam& param);

    /*
     * @brief 更新fb画布， 相当于重新创建画布
     * @param [in] param: 指定显示画布的范围, 屏幕坐标
     * @return CanvasMap指针 不为nullptr 成功; 否则 失败
     */
    const CanvasMap* UpdateCanvas(CanvasParam& param);

    /*
     * @brief 销毁画布， 相对于对CreateCanvas创建的画布做释放操作
     *      全局只能有一个画布， 因此不需要指定参数
     */
    void DeleteCanvas();

    /*
     * @brief 开始书写，如果设置了触点回调函数，则会调用回调函数处理
     * @param [in] pointerId: 指定触点的pointerId进行开始书写
     * @param [in] startPointer: 点为Canvas坐标系坐标
     */
    void StartWrite(int pointerId, PointF startPointer);

    /*
     * @brief 获取输入坐标点
     * @param [in] pointerId: 指定触点的pointerId,获取坐标点
     * @param [in] points，获取记录坐标点的vector容器，调用者创建，使用完成调用者释放, 点为Canvas坐标系坐标
     */
    void GetPointer(int pointerId, point_vector<PointF>& points);

    /*
     * @brief 停止书写时调用这个接口
     * @param [in] pointerId: 指定触点的pointerId停止书写
     */
    void StopWrite(int pointerId);

    /*
     * @brief 刷新缓存，送显
     * @param [in] flushRect: Canvas坐标，指定刷新显示的范围
     */
    void FlushCanvas(FlushRect& flushRect);

     /*
     * @brief 获取sdk版本号
     * @return const char*字符串，代表当前sdk版本的字符串
     */
    const char* GetSdkVersion();
};
}
#endif // _PEN_SPEED_INTERFACE_H